package com.gzx.spring.apis.tests.yuyao;

import com.google.gson.Gson;
import okhttp3.*;
import org.bouncycastle.jce.provider.BouncyCastleProvider;

import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.SecretKeySpec;
import java.io.IOException;
import java.math.BigInteger;
import java.nio.charset.StandardCharsets;
import java.security.*;
import java.util.*;

//RA营销分进阶版API接口文档.pdf
//融安云网分：RA营销分进阶版
public class Main1 {
	private static final String appId = "dy110g076vf53p86qxa3k7c32jkt22";
	private static final String appSecret = "1NJfNE0-8lQiaGxTf7Utl4MhVO4gaORW";

	private static final String PROVIDER = "BC";
	private static final String ALGORITHM_NAME = "SM4/ECB/PKCS7Padding";

	private static final String apiUrl = "http://test-www.makedatainfo.com/api/discern/ra_high_score";

	public static void main(String[] args) {
//        doSign();// 测试参数签名
//        doSm4();// 测试sm4加/解密

		// 测试接口
		doPost();
	}

	public static void doSign() {
		// 示例请求参数
		Map<String, String> params = new HashMap<>();
		params.put("name", "慕容");
		params.put("cardId", "110101200007286405");
		params.put("appId", appId);
		params.put("ts", "1712845613");
		params.put("version", "V1");
		params.put("requestId", "010449faaa1d4d50b068bd34f232d242");

		// 排序并生成MD5签名
		String signature = generateMD5Signature(params);

		System.out.println("MD5签名：" + signature);
	}

	public static String generateMD5Signature(Map<String, String> params) {
		try {
			// 参数排序
			SortedMap<String, String> sortedParams = new TreeMap<>(Comparator.naturalOrder());
			for (Map.Entry<String, String> entry : params.entrySet()) {
				sortedParams.put(entry.getKey(), entry.getValue() == null ? "" : entry.getValue());
			}

			// 拼接排序后的参数（不包含sign本身）
			StringBuilder paramString = new StringBuilder();
			for (Map.Entry<String, String> entry : sortedParams.entrySet()) {
				paramString.append(entry.getKey()).append("=").append(entry.getValue()).append("&");
			}

			// 移除最后一个"&"并添加盐值
			paramString.deleteCharAt(paramString.length() - 1);
			paramString.append(appSecret);

			System.out.println("待签名字符串：" + paramString);

			// 转换为UTF-8编码并计算MD5摘要
			MessageDigest md = MessageDigest.getInstance("MD5");
			byte[] hash = md.digest(paramString.toString().getBytes(StandardCharsets.UTF_8));

			// 转换为32位字符串
			return String.format("%032x", new BigInteger(1, hash));
		} catch (NoSuchAlgorithmException e) {
			throw new RuntimeException("MD5 Algorithm not available!", e);
		}
	}

	public static void doSm4() {
		// 添加BouncyCastle provider支持国密算法
		Security.addProvider(new BouncyCastleProvider());

		// 计算appSecrety的md5值
		MessageDigest md = null;
		try {
			md = MessageDigest.getInstance("MD5");
		} catch (NoSuchAlgorithmException e) {
			throw new RuntimeException(e);
		}

		byte[] hash = md.digest(appSecret.getBytes(StandardCharsets.UTF_8));
		String md5Result = String.format("%032x", new BigInteger(1, hash)).toUpperCase();
		System.out.println("appSecret md5 result: " + md5Result);

		// 密钥
		byte[] keyBytes = md5Result.substring(16, 32).getBytes(StandardCharsets.US_ASCII);
		SecretKeySpec keySpec = new SecretKeySpec(keyBytes, "SM4");

		byte[] plaintext = "hello,world!".getBytes(StandardCharsets.UTF_8);
		byte[] ciphertext = new byte[0];

		// 创建cipher实例
		Cipher cipher = null;
		try {
			cipher = Cipher.getInstance(ALGORITHM_NAME, PROVIDER);
		} catch (NoSuchAlgorithmException | NoSuchProviderException | NoSuchPaddingException e) {
			throw new RuntimeException(e);
		}

		try {
			System.out.println("源数据：" + new String(plaintext));

			// 加密
			cipher.init(Cipher.ENCRYPT_MODE, keySpec);
			ciphertext = cipher.doFinal(plaintext);

			String hexString = bytesToHex(ciphertext);
			System.out.println("加密：" + hexString);

			// 解密
			cipher.init(Cipher.DECRYPT_MODE, keySpec);
			byte[] decryptedData = cipher.doFinal(hexToBytes(hexString));
			System.out.println("解密：" + new String(decryptedData));

			// 确保解密后的数据与原始数据一致
			assert Arrays.equals(plaintext, decryptedData);

		} catch (IllegalBlockSizeException | BadPaddingException | InvalidKeyException e) {
			throw new RuntimeException(e);
		}
	}

	public static String sm4Encrypt(String content) {
		Security.addProvider(new BouncyCastleProvider());
		try {
			byte[] keyBytes = getEncryptKey().getBytes(StandardCharsets.US_ASCII);
			SecretKeySpec keySpec = new SecretKeySpec(keyBytes, "SM4");

			byte[] plaintext = content.getBytes(StandardCharsets.UTF_8);
			byte[] ciphertext;
			Cipher cipher;

			try {
				cipher = Cipher.getInstance(ALGORITHM_NAME, PROVIDER);
			} catch (NoSuchAlgorithmException | NoSuchProviderException | NoSuchPaddingException e) {
				throw new RuntimeException(e);
			}

			try {
				cipher.init(Cipher.ENCRYPT_MODE, keySpec);
				ciphertext = cipher.doFinal(plaintext);
				return bytesToHex(ciphertext).toUpperCase();
			} catch (IllegalBlockSizeException | BadPaddingException | InvalidKeyException e) {
				throw new RuntimeException(e);
			}
		} catch (NoSuchAlgorithmException e) {
			throw new RuntimeException(e);
		}
	}

	public static String getMD5String(String content) {
		MessageDigest md = null;
		try {
			md = MessageDigest.getInstance("MD5");
		} catch (NoSuchAlgorithmException e) {
			throw new RuntimeException(e);
		}
		byte[] hash = md.digest(appSecret.getBytes(StandardCharsets.UTF_8));
		return String.format("%032x", new BigInteger(1, hash)).toUpperCase();
	}

	public static String getEncryptKey() throws NoSuchAlgorithmException {
		MessageDigest md = MessageDigest.getInstance("MD5");
		byte[] hash = md.digest(appSecret.getBytes(StandardCharsets.UTF_8));
		String md5Result = String.format("%032x", new BigInteger(1, hash)).toUpperCase();
		return md5Result.substring(16, 32);
	}

	public static String bytesToHex(byte[] bytes) {
		StringBuilder sb = new StringBuilder();
		for (byte b : bytes) {
			sb.append(String.format("%02x", b));
		}
		return sb.toString();
	}

	public static byte[] hexToBytes(String s) {
		int len = s.length();
		byte[] data = new byte[len / 2];
		for (int i = 0; i < len; i += 2) {
			data[i / 2] = (byte) ((Character.digit(s.charAt(i), 16) << 4) + Character.digit(s.charAt(i + 1), 16));
		}
		return data;
	}

	public static void doPost() {
		String nameEncrypt = sm4Encrypt("冉冉");
		String idNoEncrypt = sm4Encrypt("110101200007286405");
		String phoneEncrypt = sm4Encrypt("18800307900");

		Map<String, String> params = new HashMap<>();
		params.put("name", nameEncrypt);// sm4加密后的数据
		params.put("idNo", idNoEncrypt);// sm4加密后的数据
		params.put("phone", phoneEncrypt);// sm4加密后的数据
		params.put("appId", appId);
		params.put("ts", String.valueOf(System.currentTimeMillis() / 1000));// 10位时间戳
		params.put("version", "V1");
		params.put("requestId", getMD5String("010449fa-aa1d-4d50-b068-bd34f233"));// 32位字符串：仅字母和数字组成
		String signature = generateMD5Signature(params);
		params.put("sign", signature);

		Gson gson = new Gson();
		String jsonStr = gson.toJson(params);
		System.out.println("请求数据：" + jsonStr);

		OkHttpClient client = new OkHttpClient();
		MediaType JSON = MediaType.parse("application/json; charset=utf-8");
		RequestBody body = RequestBody.create(JSON, jsonStr);
		Request request = new Request.Builder().url(apiUrl).post(body).build();

		try (Response response = client.newCall(request).execute()) {
			System.out.println(response.body().string());
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
}